﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace modul3
{
    class cSysConstr
    {
        #region privatne atributy
        private int piNextConstraintsId = 1;
        private List<cSysConstrMy> paData = new List<cSysConstrMy>();
        #endregion


        #region properties
        public int iNextConstraintsId
        {
            get { return piNextConstraintsId; }
            set { piNextConstraintsId = value; }
        }

        public List<cSysConstrMy> aData
        {
            get { return paData; }
            set { paData = value; }
        }
        #endregion


        #region uplneSingleton
        private static cSysConstr _instance;
        public static cSysConstr Instance
        {
            get
            {
                return _instance;
            }
        }
        
        public cSysConstr()
		{
            if (_instance == null)
            {
                _instance = this;
            }
            else
            {
                throw new Exception("Len raz sa ma volat konstruktor");
            }
		}
        #endregion


        #region metody
        public void konzola()
        {
            Console.WriteLine(piNextConstraintsId);
        }

        public kkRetValue CreateCon(string pa_sNazov, kkConstraintType pa_kTyp, List<int> pa_aZrojoveStlpce, List<int> pa_aReferencovaneStlpce)
        {
            kkRetValue vystup = kkRetValue.OK;
            cSysConstrMy novy = new cSysConstrMy(pa_sNazov, pa_kTyp, pa_aZrojoveStlpce, pa_aReferencovaneStlpce, iNextConstraintsId);
            if (pa_kTyp == kkConstraintType.PK)
            {
                if (pa_aReferencovaneStlpce.Count != 0)
                {
                    vystup = kkRetValue.NespravneReferencovaneStlpce;
                }
                else if (pa_aZrojoveStlpce.Count == 0)
                {
                    vystup = kkRetValue.ZiadneZdrojoveStlpce;
                }
                else
                {
                    // kontrola, ze ci nahodou uz PK neexistuje na danej tabulke (PK moze byt len jeden)
                    foreach (cSysConstrMy constraint in aData)
                    {
                        if (constraint.kTyp == kkConstraintType.PK)
                        {
                            // TO DO: kontrola, ci uz existuje v tabulke primatny kluc
                            if (false)
                            {
                                vystup = kkRetValue.AlreadyExists;
                            }
                        }
                    }
                }
            }
            else if (pa_kTyp == kkConstraintType.FK)
            {
                if (pa_aReferencovaneStlpce.Count == 0)
                {
                    vystup = kkRetValue.ZiadneReferencovaneStlpce;
                }
                else if (pa_aZrojoveStlpce.Count == 0)
                {
                    vystup = kkRetValue.ZiadneZdrojoveStlpce;
                }
                else if (pa_aZrojoveStlpce.Count != pa_aReferencovaneStlpce.Count)
                {
                    vystup = kkRetValue.NespravneReferencovaneStlpce;
                }
                else
                {
                    // kontrola, ze ci nahodou uz taky isty FK neexistuje
                    bool zdrojoveRovnake = false;
                    bool referencovaneRovnake = false;
                    int pocetNajdeniZdroj; // pocet najdenych zdrojovych stlpcov - zhody
                    int pocetNajdeniRef; // pocet najdenych referencovanych stlpcov - zhody
                    foreach (cSysConstrMy constraint in aData)
                    {
                        if (constraint.kTyp == kkConstraintType.FK && constraint.aZdrojeoveStlpce.Count == novy.aZdrojeoveStlpce.Count)
                        {
                            pocetNajdeniZdroj = 0;
                            pocetNajdeniRef = 0;
                            foreach (int column in constraint.aZdrojeoveStlpce)
                            {
                                if (novy.aZdrojeoveStlpce.Contains(column))
                                {
                                    pocetNajdeniZdroj++;
                                }
                            }
                            if (pocetNajdeniZdroj == constraint.aZdrojeoveStlpce.Count)
                            {
                                pocetNajdeniRef = 0;
                                foreach (int column in constraint.aReferencovaneStlpce)
                                {
                                    if (novy.aReferencovaneStlpce.Contains(column))
                                    {
                                        pocetNajdeniRef++;
                                    }
                                }
                            }
                            if (pocetNajdeniRef == constraint.aReferencovaneStlpce.Count)
                            {
                                vystup = kkRetValue.AlreadyExists;
                            }
                        }
                    }
                }
            }
            else
            {
                vystup = kkRetValue.Chyba;
            }

            if (vystup == kkRetValue.OK)
            {
                aData.Add(novy);
                iNextConstraintsId++;
            }
            return vystup;
        }

        private kkRetValue DropCon(cSysConstrMy pa_cDroppedConstraint)
        {
            kkRetValue vystup;
            if (aData.Remove(pa_cDroppedConstraint))
            {
                vystup = kkRetValue.OK;
            }
            else
            {
                vystup = kkRetValue.Nenajdeny;
            }
            return vystup;
        }

        public kkRetValue DropCon(int pa_iDroppedConstraint)
        {
            return DropCon(getObjectFromId(pa_iDroppedConstraint));
        }

        private cSysConstrMy getObjectFromId(int pa_iDroppedConstraint)
        {
            foreach (cSysConstrMy constrCyklus in aData)
            {
                if (constrCyklus.iId == pa_iDroppedConstraint)
                {
                    return constrCyklus;
                }
            }
            return null;
        }

        public kkConstraintType TestTyp(int pa_iConstraint)
        {
            return getObjectFromId(pa_iConstraint).kTyp;
        }

        public List<int> ShowPK(int pa_tabulka)
        {
            // bud bude treba evidovat pri constrainte tabulku,
            // alebo prejst vsetky stlpce a hladat pouzitie v constraintoch majucich typ PK a 
            // vypisat vsetky zhody
            return null;
        }
        #endregion
    }
}
